/**
  * 后端请求相关方法
  * @author: Ruan Jiazhen
  * @date: 2024-04-29 09:39:57
* */

import { ENV, ENV_CONFIG } from '@/env.config';
import { useUser } from '@/stores/user';
import { addNewTestInfo, getLocalToken } from '@/utils/local-data';

/** 普通前置url */
const baseUrl = ENV_CONFIG[ENV].BASE_URL;
/** token相关请求的前置url */
const tokenUrl = ENV_CONFIG[ENV].TOKEN_URL;
/** 商城相关请求的前置url */
const mallUrl = ENV_CONFIG[ENV].MALL_URL;

/**
 * 请求前置函数
 * @param mode 请求的模式
 */
const beforeRequest = async (mode: string) => {
  try {
  } catch (err) {
    console.error('beforeRequest error', err);
  }
};

// 请求后置函数
const afterRequest = () => {
  uni.hideLoading();
};

// XXX 旧的请求方式，考虑慢慢替换掉，最后删除
class MyRequest {
  constructor(
    baseUrl: string,
    tokenUrl: string,
    mallUrl: string,
    beforeRequest: Function,
    afterRequest: Function,
  ) {
    this.baseUrl = baseUrl;
    this.tokenUrl = tokenUrl;
    this.mallUrl = mallUrl;
    this.beforeRequest = beforeRequest;
    this.afterRequest = afterRequest;
  }

  baseUrl: string;

  tokenUrl: string;

  mallUrl: string;

  beforeRequest: Function;

  afterRequest: Function;

  requestFunction(
    url: string,
    method: string,
    isGetToken = false,
    isMallRequest = false,
    options?: any,
  ) {
    this.beforeRequest();
    return new Promise((resolve, reject) => {
      uni.request({
        url: isGetToken
          ? this.tokenUrl + url
          : isMallRequest
            ? this.mallUrl + url
            : this.baseUrl + url,
        method,
        header: { token: getLocalToken() },
        data: options.data,
        ...options,
        success: (res: any) => {
          if (res?.data?.message === '401') {
            const user = useUser();
            user.resetLoginStatus();
            return;
          }
          this.afterRequest();
          resolve(res);
        },
        fail: (err: any) => {
          this.afterRequest();
          uni.showToast({
            title: '网络错误',
            icon: 'error',
          });

          reject(err);
        },
      });
    });
  }

  get(url: string, options?: any) {
    return this.requestFunction(url, 'GET', false, false, options ?? {});
  }

  getToken(url: string, options?: any) {
    return this.requestFunction(url, 'GET', true, false, options ?? {});
  }

  post(url: string, options?: any) {
    return this.requestFunction(url, 'POST', false, false, options ?? {});
  }

  getMall(url: string, options?: any) {
    return this.requestFunction(url, 'GET', false, true, options ?? {});
  }

  postMall(url: string, options?: any) {
    return this.requestFunction(url, 'POST', false, true, options ?? {});
  }
}

export default new MyRequest(
  baseUrl,
  tokenUrl,
  mallUrl,
  beforeRequest,
  afterRequest,
);

// 请求地址灰底白字
const apiUrlStyle = 'color: #fff; background: #888; padding: 2px 4px; border-radius: 2px';
// get请求绿底白字
const getStyle = 'color: #fff; background: #07c160; padding: 2px 4px; border-radius: 2px';
// post请求蓝底白字
const postStyle = 'color: #fff; background: #1989fa; padding: 2px 4px; border-radius: 2px';

// XXX 可以使用装饰器将打印日志和记录测试信息的代码封装起来
/**
 * 普通get请求
 * @param apiUrl 请求的api地址
 * @param data 请求的参数，可选
 * @param options 请求的其他参数，可选
 */
export const reqGet = async <T extends AnyObject>(
  apiUrl: string,
  data: AnyObject = {},
  options: Optional<UniApp.RequestOptions> & {
    showLoading?: boolean;
  } = {},
) => {
  await beforeRequest('base');

  if (options.showLoading) {
    uni.showLoading({
      title: '请求中',
      mask: true,
    });
  }

  let res;
  try {
    res = await uni.request({
      url: baseUrl + apiUrl,
      method: 'GET',
      header: { token: getLocalToken() },
      data,
      ...options,
    });
    console.log(
      `%cGet%c${apiUrl}`,
      getStyle,
      apiUrlStyle,
    );
    // console.log(res);
    addNewTestInfo(apiUrl, res?.data, 'get', data, options);
  } catch (err) {
    console.error(`${apiUrl} get error`, err);
  } finally {
     if (res?.data?.message === '401') {
        const user = useUser();
        user.resetLoginStatus();
        user.isLogin = false;
        // navigateTo('login');
        return;
        }
    afterRequest();
  }

  return res as UniApp.RequestSuccessCallbackResult & {data: ResponseData<T>};
};

/**
 * 用户相关的get请求
 * @param apiUrl 请求的api地址
 * @param data 请求的参数，可选
 * @param options 请求的其他参数，可选
 */
export const reqGetAboutUser = async (
  apiUrl: string,
  data: AnyObject = {},
  options: AnyObject = {},
) => {
  await beforeRequest('token');

  try {
    const res = await uni.request({
      url: tokenUrl + apiUrl,
      method: 'GET',
      header: { token: getLocalToken() },
      data,
      ...options,
    });
    return res;
  } catch (err) {
    console.error(`${apiUrl} get error`, err);
  } finally {
    afterRequest();
  }
};

/**
 * 普通post请求
 * @param apiUrl 请求的api地址
 * @param data 请求的参数，可选
 * @param options 请求的其他参数，可选
 */
export const reqPost = async<T extends AnyObject> (
  apiUrl: string,
  data: AnyObject = {},
  options: AnyObject = {},
) => {
  await beforeRequest('base');

  let res;
  try {
    res = await uni.request({
      url: baseUrl + apiUrl,
      method: 'POST',
      header: { token: getLocalToken() },
      data,
      ...options,
    });

  } catch (err) {
    console.error(`${apiUrl} post error`, err);
  } finally {
    afterRequest();
  }
  console.log(
    `%cPost%c${apiUrl}`,
    postStyle,
    apiUrlStyle,
  );
  console.log(res);

  addNewTestInfo(apiUrl, res, 'post', data, options);
  return res as UniApp.RequestSuccessCallbackResult & { data: ResponseData<T>};
};

/** 用户相关的post请求 */
export const reqPostAboutUser = async (
  apiUrl: string,
  data: AnyObject = {},
  options: AnyObject = {},
) => {
  await beforeRequest('base');

  try {
    const res = await uni.request({
      url: tokenUrl + apiUrl,
      method: 'POST',
      header: { token: getLocalToken() },
      data,
      ...options,
    });
    return res;
  } catch (err) {
    console.error(`${apiUrl} post error`, err);
  } finally {
    if (res?.data?.message === '401') {
        const user = useUser();
        user.resetLoginStatus();
        user.isLogin = false;
        // navigateTo('login');
        return;
        }
    afterRequest();
  }
};

/**
 * 上传文件
 * @param apiUrl 请求的api地址
 * @param filePath 文件路径
 * @param data 请求的参数，可选
 * @param options 请求的其他参数，可选
 */
export const reqUploadFile = async (
  apiUrl: string,
  filePath: string,
  data: AnyObject = {},
  options: AnyObject = {},
) => {
  await beforeRequest('token');

  try {
    const res: any = await new Promise((resolve, reject) => {
      uni.uploadFile({
        url: baseUrl + apiUrl,
        filePath,
        header: {
          'Content-Type': 'application/x-www-form-urlencoded',
          token: getLocalToken(),
        },
        name: 'file',
        formData: {
          ...data,
          prefix: 'wechat-complaints',
        },
        ...options,
        success: (res: any) => {
          resolve(res);
        },
        fail: (err: any) => {
          throw err;
        },
        complete: () => {
          afterRequest();
        },
      });
    });
    return res;
  } catch (err) {
    console.error(`${apiUrl} uploadFile error`, err);
  } finally {
    afterRequest();
  }
};
